/**
 * Copyright (c) 2016-2023, Michael Yang 杨福海 (fuhai999@gmail.com).
 * <p>
 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl-3.0.txt
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.jpress.pro.filesync;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.kit.HashKit;
import com.jfinal.kit.PathKit;
import com.jfinal.kit.Ret;
import com.jfinal.upload.UploadFile;
import io.jboot.utils.FileUtil;
import io.jboot.utils.StrUtil;
import io.jboot.web.controller.JbootController;
import io.jboot.web.controller.JbootControllerContext;
import io.jpress.JPressConfig;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author michael yang (fuhai999@gmail.com)
 * @Date: 2020/3/17
 */
public class FileSyncValidator implements Interceptor {


    public static File getCurrentFile() {
        return JbootControllerContext.get().getAttr("file");
    }


    @Override
    public void intercept(Invocation inv) {

        if (!FileSyncConfig.getInstance().isEnable()) {
            inv.getController().renderError(404);
            return;
        }

        JbootController controller = (JbootController) inv.getController();
        String fileSyncSecret = FileSyncConfig.getInstance().getSecret();

        if (StrUtil.isBlank(fileSyncSecret)) {
            inv.getController().renderError(404);
            return;
        }

        List<UploadFile> uploadFiles = null;
        if (controller.isMultipartRequest()) {
            uploadFiles = controller.getFiles();
        }

        Map<String, String> parasMap = paramToMap(inv.getController().getRequest().getQueryString());
        String fileName = parasMap.get("fileName");
        if (StrUtil.isBlank(fileName)) {
            FileUtil.delete(uploadFiles);
            inv.getController().renderError(404);
            return;
        }

        String lastModified = parasMap.get("lastModified");
        if (StrUtil.isBlank(lastModified)) {
            FileUtil.delete(uploadFiles);
            inv.getController().renderError(404);
            return;
        }
        String type = parasMap.get("type");
        if (StrUtil.isBlank(type)) {
            FileUtil.delete(uploadFiles);
            inv.getController().renderError(404);
            return;
        }

        String sign = parasMap.get("sign");
        if (StrUtil.isBlank(sign)) {
            FileUtil.delete(uploadFiles);
            inv.getController().renderError(404);
            return;
        }

        fileName = StrUtil.urlDecode(fileName);
        String localSign = HashKit.md5(fileName + type + lastModified + fileSyncSecret);
        if (!sign.equals(localSign)) {
            FileUtil.delete(uploadFiles);
            inv.getController().renderError(404);
            return;
        }

        File file = null;
        int fileType = Integer.parseInt(type);
        switch (fileType) {
            case FileTypes.WEBROOT:
                file = new File(PathKit.getWebRootPath(), fileName);
                break;
            case FileTypes.TEMPLATE:
                file = new File(JPressConfig.me.getTemplateRoot(), fileName);
                break;
            case FileTypes.ADDON:
                file = new File(JPressConfig.me.getAddonRoot(), fileName);
                break;
            case FileTypes.ATTACHMENT:
                file = new File(JPressConfig.me.getAttachmentRoot(), fileName);
                break;

        }

        if (file == null) {
            FileUtil.delete(uploadFiles);
            inv.getController().renderError(404);
            return;
        }

        inv.getController().setAttr("file", file);

        try {
            inv.invoke();
            inv.getController().renderJson(Ret.ok());
        } finally {
            FileUtil.delete(uploadFiles);
        }


    }


    private static Map<String, String> paramToMap(String queryString) {
        String[] params = queryString.split("&");
        Map<String, String> resMap = new HashMap<>();
        for (int i = 0; i < params.length; i++) {
            String[] param = params[i].split("=");
            if (param.length >= 2) {
                String key = param[0];
                StringBuilder value = new StringBuilder(param[1]);
                for (int j = 2; j < param.length; j++) {
                    value.append("=").append(param[j]);
                }
                resMap.put(key, value.toString());
            }
        }
        return resMap;
    }

}
